package com.such.kit;

import com.such.kit.string.StringCommons;

/**
 * @作者 SUCH
 * @日期 2017-3-14 下午7:42:35
 * @描述 重试（当发生异常）执行指定方法
 */
public abstract class Retry<Input, Return> {

	private Input param;
	private int time = 3;
	private int interval = 3;

	public Retry() {
	}

	/**
	 * <p>构造函数</p>
	 * <p>描述：构造方法</p>
	 * @param param 参数
	 */
	public Retry(Input param) {
		this(param, 3, 3);
	}

	/**
	 * <p>构造函数</p>
	 * <p>描述：构造方法</p>
	 * @param param 参数
	 * @param time 重试次数，默认 3 次
	 * @param interval 重试间隔（秒），默认 3 秒
	 */
	public Retry(Input param, int time, int interval) {
		this.param = param;
		this.time = time;
		this.interval = interval;
	}

	/**
	 * <p>方法名：getObject</p>
	 * <p>描述：获取对象的具体实现</p>
	 * @param param 通过构造方法传入的参数
	 * @return 返回对象
	 * @throws Exception
	 */
	public abstract Return getObject(Input param) throws Exception;

	/**
	 * <p>方法名：doRetry</p>
	 * <p>描述：开始重试</p>
	 * @return getObject 的返回值
	 * @throws Exception
	 */
	public Return doRetry() throws Exception {
		Return obj = null;
		for (int i = 1; i <= this.time; i++) {
			try {
				obj = getObject(this.param);
				break;
			} catch (Exception e) {
				if (i == this.time) {
					Logger.error(getClass(), StringCommons.merger("系统已执行 ", this.time, " 次获取对象，获取对象失败："), e);
					throw new Exception(e);
				} else {
					Logger.warn(getClass(), StringCommons.merger("第 ", i, " 次获取对象失败，系统将在 ", this.interval, " 秒后再次执行"), e);
					Thread.sleep(1000 * this.interval);
				}
			}
		}
		return obj;
	}

}
